﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SetTagDialog.xaml.cs" company="GT">
//   Gunther Taborga
// </copyright>
// <summary>
//   Interaction logic for SetTagDialog.xaml
// </summary>
// --------------------------------------------------------------------------------------------------------------------

// TODO refactored=true
namespace BatchID3.Editor.Dialogs
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows;

    using BatchID3.Enumerations;
    using BatchID3.Extensions;
    using BatchID3.Mp3;

    public partial class SetTagDialog : Window, ISetTagDialog
    {
        private readonly IMp3FileSystemManager mp3FileSystemManager;

        private readonly ObservableCollection<TagToken> tagTokens;

        public SetTagDialog()
        {
            this.InitializeComponent();
        }

        public SetTagDialog(
            IMp3FileSystemManager mp3FileSystemManager, 
            IEnumerable<IMp3Entity> mp3Entities, 
            IEnumerable<TagToken> tagTokens)
        {
            this.InitializeComponent();

            this.mp3FileSystemManager = mp3FileSystemManager;
            this.Mp3Entities = mp3Entities;
            this.tagTokens = new ObservableCollection<TagToken>(tagTokens);

            this.SetupComboBox();
        }

        public event SetTagCompletedEventHandler SetTagCompleted;

        public event SetTagProgressChangedEventHandler SetTagProgressChanged;

        public IEnumerable<IMp3Entity> Mp3Entities { get; private set; }

        private object SelectedTagToken
        {
            get
            {
                return this.tagToSetComboBox.SelectedItem;
            }
        }

        private void CancelButtonClick(object sender, RoutedEventArgs e)
        {
            this.CloseDialog(false);
        }

        private void CloseDialog(bool dialogResult = true)
        {
            this.DialogResult = dialogResult;
            this.Close();
        }

        private void OkButtonClick(object sender, RoutedEventArgs e)
        {
            this.SetMp3EntitiesTagValue();
            this.CloseDialog();
        }

        private void SetMp3EntitiesTagValue()
        {
            if (this.SelectedTagToken == null)
            {
                return;
            }

            var setTagWorker = new BackgroundWorker { WorkerReportsProgress = true };
            setTagWorker.DoWork += this.SetTagWorkerDoWork;
            setTagWorker.ProgressChanged += this.SetTagProgressChangedHandler;
            setTagWorker.RunWorkerCompleted += this.SetTagWorkerRunWorkerCompleted;
            setTagWorker.RunWorkerAsync(
                new SetTagArgument(
                    this.Mp3Entities, 
                    (TagToken)this.SelectedTagToken, 
                    this.newTagValueTextbox.Text, 
                    this.prefixTextbox.Text, 
                    this.suffixTextbox.Text));
        }

        private void SetTagProgressChangedHandler(object sender, ProgressChangedEventArgs e)
        {
            var setTagState = (SetTagProgressChangedState)e.UserState;

            // Needs to happen on this thread
            this.mp3FileSystemManager.SetTagValue(
                setTagState.Mp3Entity, 
                setTagState.TagToken, 
                setTagState.Prefix, 
                setTagState.Value, 
                setTagState.Suffix);

            this.RaiseSetTagProgressChangedEvent(e);
        }

        private void RaiseSetTagProgressChangedEvent(ProgressChangedEventArgs e)
        {
            if (this.SetTagProgressChanged != null)
            {
                this.SetTagProgressChanged(this, e);
            }
        }

        private void SetTagWorkerDoWork(object sender, DoWorkEventArgs e)
        {
            var backgroundWorker = (BackgroundWorker)sender;
            var args = (SetTagArgument)e.Argument;
            var mp3Entities = args.Mp3Entities.ToList();

            for (var i = 0; i < mp3Entities.Count; i++)
            {
                backgroundWorker.ReportProgress(
                    i.PercentOf(mp3Entities.Count), 
                    new SetTagProgressChangedState(mp3Entities[i], args.TagToken, args.Prefix, args.Value, args.Suffix));
            }
        }

        private void SetTagWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.RaiseSetTagCompletedEvent();
        }

        private void RaiseSetTagCompletedEvent()
        {
            if (this.SetTagCompleted != null)
            {
                this.SetTagCompleted(this, new EventArgs());
            }
        }

        private void SetupComboBox()
        {
            foreach (var token in this.tagTokens)
            {
                this.tagToSetComboBox.Items.Add(token);
            }
        }
    }
}
